<script setup lang="ts">
import { debounce } from '@/utils/debounce'

// 详细配置见不分页的 RemoteSelect.vue
const {
  modelValue,
  apiFn,
  api,
  apiMethod = 'post',
  apiParams, // 请求参数
  labelKey = 'label', // 默认label
  valueKey = 'value',
  remote = true,
  searchKey,
  multiple = false,
  width = '100%',
} = defineProps<{
  modelValue: string | number | (string | number)[] | undefined
  apiFn?: (params: any) => Promise<any>
  api?: string
  apiMethod?: 'get' | 'post'
  apiParams?: Record<string, any>
  labelKey?: string
  valueKey?: string
  remote?: boolean // 采用本地搜索还是远程搜索
  searchKey?: string
  multiple?: boolean
  width?: string
}>()

const emit = defineEmits<{
  'update:modelValue': [string | number | (string | number)[] | undefined]
}>()

const loading = ref(false)

const options = ref<{ label: string; value: string | number }[]>([])
const total = ref(0)

const value = computed({
  get: () => modelValue,
  set: val => {
    emit('update:modelValue', val)
  },
})

const params = ref<any>({
  ...apiParams,
  pageNum: 1,
  pageSize: 10,
})

const getOptions = () => {
  loading.value = true
  if (apiFn) {
    apiFn(params.value)
      .then((res: any) => {
        total.value = res.data.total
        options.value = res.data.records.map((item: any) => ({
          label: item[labelKey],
          value: item[valueKey],
        }))
      })
      .finally(() => {
        loading.value = false
      })
  } else if (api) {
    const { fetch } = useFetch()
    fetch[apiMethod](api, params.value)
      .then((res: any) => {
        total.value = res.data.total
        options.value = res.data.records.map((item: any) => ({
          label: item[labelKey],
          value: item[valueKey],
        }))
      })
      .finally(() => {
        loading.value = false
      })
  }
}

const updatePageSize = (pageSize: number) => {
  params.value.pageSize = pageSize
  params.value.pageNum = 1
  getOptions()
}

const updatePageNum = (pageNum: number) => {
  params.value.pageNum = pageNum
  getOptions()
}

const handleSearch = debounce((query: string) => {
  if (searchKey) {
    params.value[searchKey] = query
    params.value.pageNum = 1
  }
  getOptions()
}, 500)

watch(() => apiParams, () => {
  params.value = { ...apiParams }
  getOptions()
},{
  deep: true,
})

onMounted(() => {
  getOptions()
})
</script>
<template>
  <n-select
    v-model:value="value"
    :options="options"
    filterable
    :remote="remote"
    :loading="loading"
    @search="handleSearch"
    :multiple="multiple"
    clearable
    :style="{ width }"
  >
    <template #action>
      <n-pagination
        v-model:page="params.pageNum"
        :item-count="total"
        size="small"
        :page-size="params.pageSize"
        :page-sizes="[5, 10, 20, 50]"
        @update:page-size="updatePageSize"
        @update:page="updatePageNum"
        show-size-picker
        show-quick-jumper
        :prefix="info => h('div', null, `共 ${info.itemCount} 条`)"
        :page-slot="5"
      />
    </template>
  </n-select>
</template>

<style scoped></style>
